package com.mjk.common.web.getway.transfer.http;


import cn.hutool.core.exceptions.ExceptionUtil;
import com.mjk.common.base.error.BeeError;
import com.mjk.common.base.response.BeeResponse;
import com.mjk.common.base.work.BaseWork;
import com.mjk.common.base.work.annotation.BeeWork;
import com.mjk.common.tools.gson.GsonUtils;
import com.mjk.common.tools.lambada.LambdaReflectionUtil;
import com.mjk.common.tools.logger.BizLogger;
import com.mjk.common.tools.springextend.BeeApplicationListener;
import com.mjk.common.util.*;
import com.mjk.common.web.getway.constns.GetwayConsts;
import com.mjk.common.web.getway.transfer.GetwayTransfer;
import com.mjk.common.web.getway.utils.BeeRoleUtils;
import org.apache.commons.collections.MapUtils;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.ContextRefreshedEvent;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
/**
 * http协议 ->调用http提供的微服务
 * @author mjk
 *
 */
public class HttpGetWayprotocol extends BaseWork implements GetwayTransfer, BeeApplicationListener {
	private Map<String,Object> workMapping = new ConcurrentHashMap<>();

	public Object getWork(String work){
        if (ObjectUtils.isEmpty(work)) {
            return null;
        }
		Object o = workMapping.get(work.toUpperCase());
		if(null!=o){
			return o;
		}
        return null;
	}
	@Override
    public BeeResponse invoke(Map paramMap) {
		String work = MapUtils.getString(paramMap, GetwayConsts.INSTANCE);
		String method = MapUtils.getString(paramMap, GetwayConsts.METHOD);
		try{			
			Object o = getWork(work);
            if (ObjectUtils.isEmpty(o)) {
                return BeeError.SYSTEM_INSTANCE_IS_NULL.tranceError();
            }
			//MethodAccess access = MethodAccess.get(o.getClass());		 
			Method m = ReflectionUtils.getMethodByName(AopTargetUtils.getTarget(o).getClass(), method);
			if (!BeeRoleUtils.havaRole(m)) {
				return BeeError.SYSTEM_INTERFACE_PREMEISS_ERROR.tranceError();
			}
			//判断是否需要全量返回数据
			
			Class<?> clazz = ClassUtil.loadClass(m.getParameters()[0].getParameterizedType().getTypeName());
			BeeWork beework = Objects.requireNonNull(AopTargetUtils.getTarget(o)).getClass().getAnnotation(BeeWork.class);
			BizLogger.info("work:" + work + ",method:" + method + ",params:" + GsonUtils.bean2Json(paramMap));
			if(beework.isDynamic()){
				BeeResponse rsp =  (BeeResponse) LambdaReflectionUtil.invoke(o, method, DynamicBeanUtils.getTarget(Objects.requireNonNull(clazz).newInstance(),paramMap));
				Objects.requireNonNull(rsp).setTraceId(MDCUtils.getTraceId());
				return rsp;
			}else{
				Object paramter = BeanUtils.mapToBeanIgnoreCase(paramMap, clazz);
				BeeResponse rsp =  (BeeResponse) LambdaReflectionUtil.invoke(o, method, paramter);
				Objects.requireNonNull(rsp).setTraceId(MDCUtils.getTraceId());
				return rsp;
			}			
		}catch(Exception e){
			BizLogger.error(e);
			BeeResponse response = BeeError.BEE_ERROR_FOR_ADMIN.tranceError();
			String error = ExceptionUtil.getMessage(e);
    	    response.setData(ObjectUtils.isEmpty(error)?BeeError.BEE_ERROR_FOR_ADMIN.getMsg() : error);
			response.setTraceId(MDCUtils.getTraceId());
			return response;
		}
	}
	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		ContextRefreshedEvent cEvent = (ContextRefreshedEvent)event;
		workMapping = getWorkMapping(cEvent);
	}

	public Map<String,Object> getWorkMapping(){
		return workMapping;
	}

	@Override
	public int getOrder() {		
		return 1;
	}
}
